#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using XNALibrary.Interfaces;
using XNALibrary.Cameras;
using XNALibrary.Entities;
using XNALibrary.Skybox;
using XNALibrary.PostProcessing;
using XNALibrary.Landspace;
using XNALibrary.Game;
#endregion

namespace Test1
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : XNALibrary.Game.BaseGame
    {
        protected StateManager stateManager;
        protected FilterStateManager filterStatesManager;
        protected PostProcessingManager postProcessing;
        protected Boolean enableEffect;
        protected bool Spress;
        protected bool Spress1;
        protected bool Epress;
        protected bool Epress1;

        public Game1() : base()
        {
            
        }


        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            base.Initialize();

            // TODO: Add your initialization logic here
            camera = new FreeCamera(new Vector3(0, 1000, 5000));
            ((FreeCamera)camera).Lookat = Vector3.Zero;
            ((FreeCamera)camera).NearPlane = 10.0f;
            ((FreeCamera)camera).FarPlane = 100000f;
            ((FreeCamera)camera).Speed = 1000f;
            ((FreeCamera)camera).TurnSpeed = 30;
            
            #region States
            stateManager = new StateManager();

            //Scene Car
            SceneCar sceneCar = new SceneCar();
            stateManager.States.Add(sceneCar);

            //SpaceShip
            SpaceShip spaceShip = new SpaceShip();
            stateManager.States.Add(spaceShip);

            //Scene Landspace
            SceneLandspace sceneLandspace = new SceneLandspace();
            stateManager.States.Add(sceneLandspace);

            stateManager.Initialize(content, graphics.GraphicsDevice); 

            #endregion

            #region Filters
            postProcessing = new PostProcessingManager();
            filterStatesManager = new FilterStateManager();

            //NormalFilter
            FilterState normalRender = new FilterState();
            NormalRenderFilter normaRenderFilter = new NormalRenderFilter(0);
            normalRender.Filters.Add(normaRenderFilter);
            filterStatesManager.FilterStates.Add(normalRender);
            //FirstFilter
            filterStatesManager.NextFilter(postProcessing);

            //Black&White
            FilterState BlackWhite = new FilterState();
            BlackWhiteFilter bwFilter = new BlackWhiteFilter(0);
            BlackWhite.Filters.Add(bwFilter);
            filterStatesManager.FilterStates.Add(BlackWhite);

            //Tiling
            FilterState Tiling = new FilterState();
            TilingFilter tilingFilter = new TilingFilter(0);
            Tiling.Filters.Add(tilingFilter);
            filterStatesManager.FilterStates.Add(Tiling);

            //RadialBlur
            FilterState RadialBlur = new FilterState();
            RadialBlurFilter radialBlurFilter = new RadialBlurFilter(0);
            RadialBlur.Filters.Add(radialBlurFilter);
            filterStatesManager.FilterStates.Add(RadialBlur);

            //Glass
            FilterState Glass = new FilterState();
            GlassFilter glassFilter = new GlassFilter(0);
            Glass.Filters.Add(glassFilter);
            filterStatesManager.FilterStates.Add(Glass);

            //OldMovie
            FilterState OldMovie = new FilterState();
            OldMovieFilter oldMovieFilter = new OldMovieFilter(0);
            OldMovie.Filters.Add(oldMovieFilter);
            filterStatesManager.FilterStates.Add(OldMovie);

            //CellShading
            FilterState CellShading = new FilterState();
            SobelFilter sobel = new SobelFilter(0);
            CombineFilter combine = new CombineFilter(0, 1,CombineFilter.Techniques.SobelCombine);

            CellShading.Filters.Add(sobel);
            CellShading.Filters.Add(combine);
            filterStatesManager.FilterStates.Add(CellShading);

            //Bloom
            FilterState Bloom = new FilterState();
            SaturateFilter saturate = new SaturateFilter(0, 0.7f);
            GaussianBlurFilter gaussianH = new GaussianBlurFilter(1, GaussianBlurFilter.Direction.Horizontal);
            GaussianBlurFilter gaussianV = new GaussianBlurFilter(2, GaussianBlurFilter.Direction.Vertical);
            CombineFilter combineBloom = new CombineFilter(0, 3);

            Bloom.Filters.Add(saturate);
            Bloom.Filters.Add(gaussianH);
            Bloom.Filters.Add(gaussianV);
            Bloom.Filters.Add(combineBloom);

            filterStatesManager.FilterStates.Add(Bloom);

            #endregion

        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void UpdateGame()
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
                this.Exit();

            ((FreeCamera)BaseGame.camera).Update();

            stateManager.Update();

            GamePadState gamePad = GamePad.GetState(PlayerIndex.One);
            if (gamePad.IsConnected)
            {
                if (gamePad.Buttons.RightShoulder == ButtonState.Pressed)
                    Spress = true;
                else if (Spress)
                {
                    stateManager.NextState();
                    Spress = false;
                }

                if (gamePad.Buttons.LeftShoulder == ButtonState.Pressed)
                    Spress1 = true;
                else if (Spress1)
                {
                    stateManager.PreviousState();
                    Spress1 = false;
                }

                if (gamePad.Triggers.Right > 0)
                    Epress = true;
                else if (Epress)
                {
                    filterStatesManager.NextFilter(postProcessing);
                    Epress = false;
                }

                if (gamePad.Triggers.Left > 0)
                    Epress1 = true;
                else if (Epress1)
                {
                    filterStatesManager.PreviousFilter(postProcessing);
                    Epress1 = false;
                }
            }

        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Render()
        {
            stateManager.Draw();

            postProcessing.PostRender();
        }
    }
}
